package com.bh.ledger.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bh.common.annotation.DataDictClass;
import com.bh.common.constant.Entity;
import com.bh.common.constant.VerifiZbStatus;
import com.bh.common.exception.ServiceException;
import com.bh.common.utils.DateUtils;
import com.bh.common.utils.SecurityUtils;
import com.bh.extend.domain.JcCustomerPrice;
import com.bh.extend.domain.JcCustomerVolumePrice;
import com.bh.extend.service.IJcCustomerPriceService;
import com.bh.extend.vo.JcCustomerPriceQueryVo;
import com.bh.fee.domain.JcFeeType;
import com.bh.fee.service.IJcFeeTypeService;
import com.bh.ledger.convert.JcLedgerDetailConvert;
import com.bh.ledger.domain.JcLedgerDetail;
import com.bh.ledger.domain.JcVerificationRecord;
import com.bh.ledger.domain.JcVerificationZb;
import com.bh.ledger.mapper.JcLedgerDetailMapper;
import com.bh.ledger.mapper.JcVerificationRecordMapper;
import com.bh.ledger.service.IJcLedgerDetailService;
import com.bh.ledger.service.IJcVerificationZbService;
import com.bh.ledger.vo.JcCustomerLedgerDetail;
import com.bh.ledger.vo.JcLedgerDetailGenerateVo;
import com.bh.ledger.vo.JcLedgerDetailVo;
import com.bh.order.domain.JcOrder;
import com.bh.order.domain.JcOrderProduct;
import com.bh.order.domain.JcOrderReceivingParty;
import com.bh.order.mapper.JcOrderMapper;
import com.bh.order.service.IJcOrderHandleService;
import com.bh.order.service.IJcOrderReceivingPartyService;
import com.bh.shipment.domain.JcShipment;
import com.bh.shipment.mapper.JcShipmentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 台帐明细Service业务层处理
 *
 * @author slx
 * @date 2023-04-24
 */

@Service
public class JcLedgerDetailServiceImpl extends ServiceImpl<JcLedgerDetailMapper, JcLedgerDetail> implements IJcLedgerDetailService {
    @Autowired
    private JcLedgerDetailMapper jcLedgerDetailMapper;
    @Autowired
    private JcLedgerDetailConvert jcLedgerDetailConvert;
    @Autowired
    private JcOrderMapper jcOrderMapper;
    @Autowired
    private JcShipmentMapper jcShipmentMapper;
    @Autowired
    private IJcCustomerPriceService jcCustomerPriceService;
    @Autowired
    private IJcFeeTypeService feeTypeService;
    @Autowired
    private IJcVerificationZbService jcVerificationZbService;
    @Autowired
    private IJcOrderReceivingPartyService jcOrderReceivingPartyService;
    /**
     * 查询台帐明细
     *
     * @param id 台帐明细主键
     * @return 台帐明细
     */
    @DataDictClass
    @Override
    public JcLedgerDetail selectJcLedgerDetailById(Long id) {
        return jcLedgerDetailMapper.selectById(id);
    }


    @Override
    public List<JcLedgerDetail> selectJcLedgerDetailListByShipmentId(Long shipmentId) {
        JcLedgerDetail jcLedgerDetail = new JcLedgerDetail();
        jcLedgerDetail.setJcShipmentId(shipmentId);
        return jcLedgerDetailMapper.selectJcLedgerDetailList(jcLedgerDetail);
    }


    @Override
    public List<JcLedgerDetail> selectNoUseJcLedgerDetailListByField1(String filed1) {
        return jcLedgerDetailMapper.selectNoUseJcLedgerDetailListByField1(filed1);
    }

    /**
     * 查询台帐明细列表
     *
     * @param jcLedgerDetail 台帐明细
     * @return 台帐明细
     */
    @DataDictClass
    @Override
    public List<JcLedgerDetail> selectJcLedgerDetailList(JcLedgerDetail jcLedgerDetail) {
        return jcLedgerDetailMapper.selectJcLedgerDetailList(jcLedgerDetail);
    }


    @DataDictClass
    @Override
    public List<JcCustomerLedgerDetail> selectJcCustomerLedgerDetailList(JcCustomerLedgerDetail jcLedgerDetail) {
        return jcLedgerDetailMapper.selectJcCustomerLedgerDetailList(jcLedgerDetail);
    }


    @DataDictClass
    @Override
    public List<JcLedgerDetail> selectJcLedgerDetailListByOrderId(Long orderId) {
        return jcLedgerDetailMapper.selectJcLedgerDetailListByOrderId(orderId);
    }

    /**
     * 查询派送员台帐明细列表，禁止查看他人数据
     *
     * @param orderId
     * @return
     */
    @DataDictClass
    @Override
    public List<JcLedgerDetailVo> selectJcLedgerDetailVoListByOrderId(Long orderId) {
        List<JcLedgerDetail> list = jcLedgerDetailMapper.selectJcLedgerDetailListByOrderId(orderId);
        return jcLedgerDetailConvert.toVoList(list);
    }

    @Override
    public int manualGenerate(JcLedgerDetailGenerateVo generateVo) {
        int num = 0;
        // 查询客户所有订单
        List<JcOrder> orderList = jcOrderMapper.selectJcOrderListByCustomerId(generateVo.getJcCustomerId(), generateVo.getStartDate(), generateVo.getEndDate());
        if (orderList == null || orderList.isEmpty()) {
            throw new ServiceException("客户没有订单");
        }
        for (JcOrder order : orderList) {
            // 如果存在手动订单则不增加
            List<JcLedgerDetail> ledgerDetails = jcLedgerDetailMapper.selectAutoAddJcLedgerDetailListByOrderId(order.getId());
            if (ledgerDetails != null && !ledgerDetails.isEmpty()) {
                continue;
            }
            // 查询收获地址的类型
            List<JcOrderReceivingParty> orderReceivingParties = jcOrderReceivingPartyService.selectJcOrderReceivingpartyListByOrderId(order.getId());
            String addressType = "city";
            for (JcOrderReceivingParty orderReceivingParty : orderReceivingParties) {
                if (orderReceivingParty.getType() == 1) {
                    addressType = orderReceivingParty.getAddressType();
                }
            }
            Map<String, Object> priceMap = insertLedgerDetailByPrice(order, addressType);
            List<JcLedgerDetail> orderLedgerDetails = priceMap.get("ledgerDetails") == null ? new ArrayList<>() : (List<JcLedgerDetail>) priceMap.get("ledgerDetails");
            BigDecimal incomePrice = (BigDecimal) priceMap.get("incomePrice");
            if (orderLedgerDetails.isEmpty()) {
                throw new ServiceException("没有生成任何数据，请检查订单" + order.getCode() +"的客户的相关路线原始价格配置");
            }
            //未核销金额
            BigDecimal whxje = BigDecimal.ZERO, agent = BigDecimal.ZERO, totalAmount = BigDecimal.ZERO, input = BigDecimal.ZERO;
            for (JcLedgerDetail detail : orderLedgerDetails) {
                if (SecurityUtils.getUserId() == null) {
                    detail.setCreateName("admin");
                }
                detail.setCreateTime(DateUtils.getNowDate());
                totalAmount  = totalAmount.add(detail.getAmount());
                input = input.add(detail.getIncome());
                // 处理总额问题
                BigDecimal amount = detail.getAmount();
                whxje = whxje.add(detail.getAmount());
                if (amount.compareTo(BigDecimal.ZERO) > 0) {
                    //处理代收货款
                    JcFeeType feeType = feeTypeService.selectJcFeeTypeById(detail.getJcFeeTypeId());
                    if (feeType.getIsCount() != null && detail.getIncome().compareTo(BigDecimal.ZERO) > 0) {
                        int isCount = feeType.getIsCount();
                        if (isCount == 1) {
                            //如果是代收代付类的
                            agent = agent.add(amount);
                        }
                    }
                }
            }
            if (incomePrice.compareTo(BigDecimal.ZERO) > 0) {
                // 更新均价
                order.setPrice(incomePrice);
                order.setWhxMoney(whxje);
                order.setAgent(agent);
                order.setPrice(incomePrice);
                jcOrderMapper.updateById(order);
            }
            num += jcLedgerDetailMapper.insertBatch(orderLedgerDetails);
            insertHxzb(order.getId(), totalAmount, input);
        }
        return num;
    }


    // 插入核销总表
    public void insertHxzb(Long orderId, BigDecimal amount, BigDecimal input) {
        //订单确认后，向核销表插入一条数据
        JcVerificationZb verificationZb = new JcVerificationZb();
        verificationZb.setJcOrganizationId(SecurityUtils.getOrgId());
        verificationZb.setJcOrderId(orderId);
        verificationZb.setStatus(VerifiZbStatus.UNACTIVE);
        verificationZb.setHxStatus(0);
        verificationZb.setWhxMoney(amount);
        verificationZb.setZmoney(amount);
        verificationZb.setZinput(input);
        verificationZb.setHxCount(0);
        verificationZb.setType(0);
        verificationZb.setHxMoney(BigDecimal.ZERO);
        verificationZb.setTzSource(0L);
        verificationZb.setCreateName(SecurityUtils.getUsername());
        verificationZb.setCreateTime(DateUtils.getNowDate());
        jcVerificationZbService.insertJcVerificationZb(verificationZb);
    }

    /**
     * 新增台帐明细
     *
     * @param jcLedgerDetail 台帐明细
     * @return 结果
     */
    @Override
    public int insertJcLedgerDetail(JcLedgerDetail jcLedgerDetail) {
        // 交付方式为 0自提
        if (0L == jcLedgerDetail.getType()) {
            JcOrder order = jcOrderMapper.selectById(jcLedgerDetail.getJcOrderId());
            if (order.getHandoverType() == 0) {
                if (132L == jcLedgerDetail.getJcFeeTypeId() && jcLedgerDetail.getAmount().compareTo(BigDecimal.ZERO) > 0) {
                    throw new ServiceException("交付方式是自提的，没有送货费");
                }
            }
        }
        jcLedgerDetail.setCreateName(SecurityUtils.getUsername());
        jcLedgerDetail.setCreateTime(DateUtils.getNowDate());
        jcLedgerDetail.setIsConfirm(0);
        jcLedgerDetail.setStatus(Entity.ACTIVE);
        return jcLedgerDetailMapper.insert(jcLedgerDetail);
    }

    /**
     * 修改台帐明细
     *
     * @param jcLedgerDetail 台帐明细
     * @return 结果
     */
    @Override
    public int updateJcLedgerDetail(JcLedgerDetail jcLedgerDetail) {
        // 交付方式为 0自提
        JcOrder order = jcOrderMapper.selectById(jcLedgerDetail.getJcOrderId());
        if (order.getHandoverType() == 0) {
            if ("132".equals(jcLedgerDetail.getJcFeeTypeId()) && jcLedgerDetail.getAmount().compareTo(BigDecimal.ZERO) > 0) {
                throw new ServiceException("交付方式是自提的，没有送货费");
            }
        }
        jcLedgerDetail.setModifyName(SecurityUtils.getUsername());
        jcLedgerDetail.setModifyTime(DateUtils.getNowDate());
        return jcLedgerDetailMapper.updateById(jcLedgerDetail);
    }

    /**
     * 批量删除台帐明细
     *
     * @param ids 需要删除的台帐明细主键
     * @return 结果
     */
    @Override
    public int deleteJcLedgerDetailByIds(Long[] ids) {
        return jcLedgerDetailMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除台帐明细信息
     *
     * @param id 台帐明细主键
     * @return 结果
     */
    @Override
    public int deleteJcLedgerDetailById(Long id) {
        return jcLedgerDetailMapper.deleteById(id);
    }

    @Override
    public int deleteByShipmentId(Long shipmentId) {
        return jcLedgerDetailMapper.deleteByShipmentId(List.of(shipmentId));
    }

    @Override
    public int confirm(Long orderId, Date date) {
        JcLedgerDetail ledgerDetail = jcLedgerDetailMapper.selectById(orderId);
        ledgerDetail.setIsConfirm(1);
        if (date != null) {
            ledgerDetail.setAffirmTime(date);
        } else {
            ledgerDetail.setAffirmTime(new Date());
        }
        // 将订单的是否收入状态改为已收入
        if (ledgerDetail.getJcOrderId() != null) {
            JcOrder jcOrder = jcOrderMapper.selectById(ledgerDetail.getJcOrderId());
            jcOrder.setIsConfirm(1);
            jcOrderMapper.updateById(jcOrder);
        }

        if (ledgerDetail.getJcShipmentId() != null) {
            // 将运单的是否收入状态改为已收入
            JcShipment jcShipment = jcShipmentMapper.selectById(ledgerDetail.getJcShipmentId());
            jcShipment.setIsConfirm(1);
            jcShipmentMapper.updateById(jcShipment);
        }
        // 将运单的是否收入状态改为已收入
        return jcLedgerDetailMapper.updateById(ledgerDetail);
    }

    @Override
    public int unconfirmed(Long id) {
        JcLedgerDetail ledgerDetail = jcLedgerDetailMapper.selectById(id);
        // 将订单的是否收入状态改为已收入
        if (ledgerDetail.getJcOrderId() != null) {
            JcOrder jcOrder = jcOrderMapper.selectById(ledgerDetail.getJcOrderId());
            jcOrder.setIsConfirm(0);
            jcOrderMapper.updateById(jcOrder);
        }

        if (ledgerDetail.getJcShipmentId() != null) {
            // 将运单的是否收入状态改为已收入
            JcShipment jcShipment = jcShipmentMapper.selectById(ledgerDetail.getJcShipmentId());
            jcShipment.setIsConfirm(0);
            jcShipmentMapper.updateById(jcShipment);
        }
        // 将运单的是否收入状态改为已收入
        return jcLedgerDetailMapper.unconfirmed(id);
    }

    @Override
    public Map<String, Object> insertLedgerDetailByPrice(JcOrder order, String addressType) {
        // 先生成可能存在的单据，查询价格
        JcCustomerPriceQueryVo queryVo = new JcCustomerPriceQueryVo();
        queryVo.setCustomerId(order.getJcCustomerId());
        queryVo.setJcOrganizationId(order.getJcOrganizationId());
        queryVo.setFromOrg(order.getJcFromOrganizationId());
        queryVo.setToOrg(order.getJcToOrganizationId());
        queryVo.setFromServerZoneId(order.getJcStartZoneId());
        queryVo.setToServerZoneId(order.getJcEndZoneId());
        JcCustomerPrice customerPrice = jcCustomerPriceService.selectJcCustomerPriceInfo(queryVo);
        // 正常价格
        BigDecimal incomePrice = BigDecimal.ZERO;
        BigDecimal trunkOutcomePrice = BigDecimal.ZERO;
        BigDecimal townOutcomePrice = BigDecimal.ZERO;
        List<JcLedgerDetail> ledgerDetails = new ArrayList<>();
        if (customerPrice != null) {
            List<JcCustomerVolumePrice> customerVolumePrices = new ArrayList<>();
            if (order.getJsType() == 2) {
                customerVolumePrices = jcCustomerPriceService.selectJcCustomerVolumePriceByPriceId(customerPrice.getId());
            }
            Map<String, List<JcOrderProduct>> orderProductMap = order.getOrderProducts().stream().collect(Collectors.groupingBy(JcOrderProduct::getPackageType));

            if (order.getJsType() == 0) {
                incomePrice = customerPrice.getIncomeWeightPrice();
                trunkOutcomePrice = customerPrice.getTrunkWeightPrice();
                townOutcomePrice = customerPrice.getRegionalWeightPrice();
            } else if (order.getJsType() == 1) {
                incomePrice = customerPrice.getIncomeNumPrice();
                trunkOutcomePrice = customerPrice.getTrunkNumPrice();
                townOutcomePrice = customerPrice.getRegionalNumPrice();
            }
            BigDecimal pickOutcomePrice = customerPrice.getPickupPrice();
            BigDecimal otherOutcomePrice = customerPrice.getOtherSpendPrice();
            // 总收入（分为三种，按件(重量)费用，按冷藏箱费用，按体积费用）
            BigDecimal income = BigDecimal.ZERO;
            // 干线支出
            BigDecimal trunkOutcome = BigDecimal.ZERO;
            //乡镇送货支出
            BigDecimal townOutcome = BigDecimal.ZERO;
            // 取货费用(默认全部按件处理)
            BigDecimal pickOutcome = BigDecimal.ZERO;
            // 其他支出(默认全部按件处理)
            BigDecimal otherOutcome = BigDecimal.ZERO;
            // 单独处理冷冻箱价格问题，冷冻箱包括 21:冷藏箱(20L),22:冷藏箱(60升),23:冷藏箱(61升以上)
            List<String> packageTypeList = Arrays.asList("21", "22", "23");
            for (String key : orderProductMap.keySet()) {
                List<JcOrderProduct> pts1 = orderProductMap.get(key);
                int totalNumber = pts1.stream().mapToInt(JcOrderProduct::getNumber).sum();
                BigDecimal totalWeight = pts1.stream().map(JcOrderProduct::getWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal totalVolume = pts1.stream().map(JcOrderProduct::getVolume).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

                // 从customerVolumePrices获取体积价格
                if (order.getJsType() == 2) {
                    JcCustomerVolumePrice volumePrice = customerPrice.getVolumePrice(totalVolume, customerVolumePrices);
                    incomePrice = volumePrice.getPriceValue();
                    trunkOutcomePrice = volumePrice.getTrunkPrice();
                    townOutcomePrice = volumePrice.getRegionalPrice();
                } else {
                    if (packageTypeList.contains(key)) {
                        // 冷冻箱全部使用
                        incomePrice = customerPrice.getIncomeFreezerPrice(key);
                        trunkOutcomePrice = customerPrice.getTrunkOutcomeFreezerPrice(key);
                        townOutcomePrice = customerPrice.getTownOutcomeFreezerPrice(addressType, key);
                    }
                }
                // 0:按重量 1:按件数 2:按体积
                switch (order.getJsType()) {
                    case 0:
                        income = income.add(incomePrice.multiply(totalWeight));
                        trunkOutcome = trunkOutcome.add(trunkOutcomePrice.multiply(totalWeight));
                        townOutcome = townOutcome.add(townOutcomePrice.multiply(totalWeight));
                        break;
                    case 1:
                        income = income.add(incomePrice.multiply(BigDecimal.valueOf(totalNumber)));
                        trunkOutcome = trunkOutcome.add(trunkOutcomePrice.multiply(BigDecimal.valueOf(totalNumber)));
                        townOutcome = townOutcome.add(townOutcomePrice.multiply(BigDecimal.valueOf(totalNumber)));
                        break;
                    case 2:
                        income = income.add(incomePrice.multiply(totalVolume));
                        trunkOutcome = trunkOutcome.add(trunkOutcomePrice.multiply(totalVolume));
                        townOutcome = townOutcome.add(townOutcomePrice.multiply(totalVolume));
                        break;
                    default:
                        break;
                }
                // 以下数据按件处理
                pickOutcome = pickOutcome.add(pickOutcomePrice.multiply(BigDecimal.valueOf(totalNumber)));
                otherOutcome = otherOutcome.add(otherOutcomePrice.multiply(BigDecimal.valueOf(totalNumber)));
            }
            // 新增一条默认的台账，默认为基础运费，即总收入,大于0才新增
            if (income.compareTo(BigDecimal.ZERO) > 0) {
                JcLedgerDetail ledgerDetail = new JcLedgerDetail();
                ledgerDetail.setJcOrderId(order.getId());
                ledgerDetail.setCategory(0);
                ledgerDetail.setType(0);
                // 代表运费
                JcFeeType feeType = feeTypeService.selectJcFeeTypeByCode("YF");
                ledgerDetail.setJcFeeTypeId(feeType.getId());
                ledgerDetail.setJcFeeTypeCode("YF");
                ledgerDetail.setTaxrate(BigDecimal.valueOf(0.09));
                ledgerDetail.setStatus(Entity.ACTIVE);
                ledgerDetail.setIsConfirm(0);
                ledgerDetail.setCollectMethod("0");
                ledgerDetail.setSettlementMethod("0");
                //更具选中的类型判断(收入默认加税0.09，支出则不需要加税)
                ledgerDetail.setInput(income.multiply(BigDecimal.valueOf(0.09)));
                ledgerDetail.setAmount(income);
                ledgerDetail.setIncome(ledgerDetail.getAmount().subtract(ledgerDetail.getInput()));
                ledgerDetails.add(ledgerDetail);
            }

            //处理支出费用 处理四种 干线订单运费 GXDDYF 提派运费 DPYF 其他费 QTFY 取货费用QHFY
            Map<String, BigDecimal> priceList = new HashMap<>();
            priceList.put("GXDDYF", trunkOutcome);
            priceList.put("DPYF", townOutcome);
            priceList.put("QHFY", pickOutcome);
            priceList.put("QTFY", otherOutcome);
            addLedgerDetails(ledgerDetails, order, priceList);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("ledgerDetails", ledgerDetails);
        result.put("incomePrice", incomePrice);
        return result;
    }

        /**
         * 保存费用 ledgerDetail订单
         *
         * @param ledgerDetails
         * @param jcOrder
         * @param priceList
         */
        private void addLedgerDetails(List<JcLedgerDetail> ledgerDetails, JcOrder jcOrder, Map<String, BigDecimal> priceList) {
            // 处理支出费用 处理四种 干线订单运费 GXDDYF 提派运费 DPYF 其他费 QTFY 取货费用QHFY
            for (Map.Entry<String, BigDecimal> entry : priceList.entrySet()) {
                if (entry.getValue() != null && entry.getValue().compareTo(BigDecimal.ZERO) > 0) {
                    JcLedgerDetail ledgerDetail = new JcLedgerDetail();
                    // 使用这个字段来存储订单id，后期装载的时候使用修改为运单
                    ledgerDetail.setField1(String.valueOf(jcOrder.getId()));
                    ledgerDetail.setJcCarrierId(1L);
                    ledgerDetail.setCategory(0);
                    ledgerDetail.setType(1);
                    ledgerDetail.setTaxrate(BigDecimal.ZERO);
                    // 代表运费
                    JcFeeType feeType = feeTypeService.selectJcFeeTypeByCode(entry.getKey());
                    ledgerDetail.setJcFeeTypeId(feeType.getId());
                    ledgerDetail.setJcFeeTypeCode(entry.getKey());
                    ledgerDetail.setIsConfirm(0);
                    ledgerDetail.setStatus(Entity.ACTIVE);
                    ledgerDetail.setOutcome(entry.getValue());
                    ledgerDetail.setAmount(entry.getValue());
                    ledgerDetails.add(ledgerDetail);
                }
            }
        }
}
